package cn.lingyangwl.agile.infra.gen.service.impl;

import cn.lingyangwl.agile.infra.gen.assembly.*;
import cn.lingyangwl.agile.infra.gen.manager.*;
import cn.lingyangwl.agile.infra.gen.mapper.*;
import cn.lingyangwl.agile.infra.gen.model.entity.*;
import cn.lingyangwl.agile.infra.gen.model.rqrs.*;
import cn.lingyangwl.agile.infra.gen.service.*;
import cn.lingyangwl.agile.infra.gen.utils.*;
import cn.lingyangwl.framework.mybatis.plus.utils.*;
import cn.lingyangwl.framework.tool.core.exception.*;
import cn.lingyangwl.framework.validation.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shenguangyang
 */
@Slf4j
@Service
public class TemplateConfigServiceImpl implements TemplateConfigService {
    @Resource
    private TemplateConfigMapper templateConfigMapper;

    @Resource
    private TemplateConfigAssembly templateConfigAssembly;

    @Resource
    private TemplateConfigManager templateConfigManager;
    @Resource
    private TemplateGroupManager templateGroupManager;

    @Override
    public List<TemplateConfig> listByIds(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return new ArrayList<>();
        }
        return templateConfigMapper.selectBatchIds(idList);
    }

    @Override
    public TemplateConfig getById(Long id) {
        return templateConfigMapper.selectById(id);
    }

    @Override
    public List<TemplateConfig> listAll() {
        return templateConfigMapper.selectList(new LambdaQueryWrapper<>());
    }

    @Override
    public boolean save(TemplateConfigReq rq) {
        TemplateConfig templateConfig = templateConfigAssembly.toTemplateConfig(rq);
        handleContent(templateConfig);
        String name = templateConfig.getName();
        LambdaQueryWrapper<TemplateConfig> wrapper = Wrappers.<TemplateConfig>lambdaQuery()
                .eq(TemplateConfig::getName, name)
                .eq(TemplateConfig::getGroupId, templateConfig.getGroupId());
        TemplateConfig existObj = templateConfigMapper.selectOne(wrapper);
        if (existObj != null) {
            throw new BizException("模板名称 "+ name +" 已存在");
        }
        return templateConfigMapper.insert(templateConfig) > 0;
    }

    @Override
    public void updateById(TemplateConfigReq req) {
        TemplateConfig templateConfig = templateConfigAssembly.toTemplateConfig(req);
        if (templateConfigMapper.updateById(templateConfig) <= 0) {
            throw new BizException("更新失败");
        }
    }

    @Override
    public void deleteById(TemplateConfig templateConfig) {
        if (templateConfigMapper.deleteById(templateConfig) <= 0) {
            throw new BizException("删除失败");
        }
    }

    @Override
    public List<TemplateConfigResp> listByGroupId(Long groupId) {
        LambdaQueryWrapper<TemplateConfig> wrapper = Wrappers.<TemplateConfig>lambdaQuery()
                .eq(TemplateConfig::getGroupId, groupId).orderByDesc(TemplateConfig::getCreatedAt);
        return templateConfigMapper.selectList(wrapper).stream()
                .map(templateConfigAssembly::toTemplateConfigRS).collect(Collectors.toList());
    }

    @Override
    public void copyById(CopyTemplateReq req) {
        TemplateConfig templateConfig = templateConfigManager.getById(req.getId());
        if(templateConfig == null){
            throw new BizException("要复制的模板不存在 templateId: {}", req.getId());
        }
        TemplateConfig checkTemplateConfig = templateConfigManager.getTemplateByName(req);
        if (Objects.nonNull(checkTemplateConfig) &&
                checkTemplateConfig.getGroupId().equals(req.getTargetGroupId()) &&
                checkTemplateConfig.getName().equals(req.getName())) {
            throw new BizException("同组下, 新模板名称 {} 不能和旧模板名称相同", req.getName());
        }
        templateConfig.setId(null);
        templateConfig.setName(req.getName());
        templateConfig.setGroupId(req.getTargetGroupId());
        Assert.isTrue(templateConfigMapper.insert(templateConfig) > 0, "复制失败");
    }

    @Override
    public IPage<TemplateConfig> page(TemplateQueryReq req) {
        LambdaQueryWrapper<TemplateConfig> lqw = TemplateConfig.lqw()
                .eq(Objects.nonNull(req.getGroupId()), TemplateConfig::getGroupId, req.getGroupId())
                .like(StringUtils.isNotEmpty(req.getName()), TemplateConfig::getName, req.getName())
                .orderByDesc(TemplateConfig::getCreatedAt);
        IPage<TemplateConfig> page=  templateConfigManager.page(PageUtil.to(req), lqw);

        Map<Long, String> idMap = templateGroupManager.list()
                .stream()
                .collect(Collectors.toMap(TemplateGroup::getId, TemplateGroup::getGroupName));
        for (TemplateConfig templateConfig : page.getRecords()) {
            Long gid = templateConfig.getGroupId();
            if (gid != null) {
                String groupName = idMap.getOrDefault(gid, "");
                templateConfig.setGroupName(groupName);
            }
            templateConfig.setContent(TemplateMetaUtils.generateMetaContent(templateConfig));
        }
        return page;
    }

    /**
     * 解析模板元信息, 即开始第一行是注释时
     * <p>
     * 格式: ## filename=#{xxx}.java, folder=entity
     */
    private void handleContent(TemplateConfig template) {
        String content = StringUtils.trim(template.getContent());
        // 解析元信息
        Map<String, String> data = TemplateMetaUtils.parseMetaContent(content);
        if (StringUtils.isEmpty(template.getFileName())) {
            template.setFileName(data.get("filename"));
        }
        if (StringUtils.isEmpty(template.getFolder())) {
            template.setFolder(data.get("folder"));
        }
        // 设置默认值
        if (StringUtils.isEmpty(template.getFileName())) {
            template.setFileName(template.getName());
        }
        if (StringUtils.isEmpty(template.getFolder())) {
            template.setFolder(template.getName());
        }
    }

    @Override
    public void deleteBatchByIds(List<Long> ids) {
        templateConfigManager.removeByIds(ids);
    }

    @Override
    public List<TemplateConfig> list(TemplateQueryReq req) {
        LambdaQueryWrapper<TemplateConfig> queryWrapper = TemplateConfig.lqw()
                .eq(Objects.nonNull(req.getGroupId()), TemplateConfig::getGroupId, req.getGroupId())
                .like(StringUtils.isNotEmpty(req.getName()), TemplateConfig::getName, req.getName())
                .orderByDesc(TemplateConfig::getCreatedAt);
        return templateConfigManager.list(queryWrapper);
    }

    @Override
    public String importExcel(List<TemplateConfig> list, Long groupId, boolean updateSupport) {
        if (CollectionUtils.isEmpty(list)) {
            throw new BizException("导入模板数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 校验模板组是否存在
        if (templateGroupManager.getById(groupId) == null) {
            throw new BizException("请选择模板组");
        }
        for (TemplateConfig item : list) {
            try {
                item.setId(null);
                item.setGroupId(groupId);
                TemplateConfig templateConfig = templateConfigManager.getTemplateByNameInGroup(item.getName(), item.getGroupId());
                if (Objects.isNull(templateConfig)) {
                    ValidationUtils.validateAll(item);
                    templateConfigManager.save(item);
                    successNum++;
                    successMsg.append(successNum).append("、模板 ").append(item.getName()).append(" 导入成功").append("<br/>");
                } else if (updateSupport) {
                    ValidationUtils.validateAll(item);
                    item.setId(templateConfig.getId());
                    templateConfigManager.updateByNameAndGroup(item);
                    successNum++;
                    successMsg.append(successNum).append("、模板 ").append(item.getName()).append(" 更新成功").append("<br/>");
                } else {
                    failureNum++;
                    failureMsg.append(failureNum).append("、模板 ").append(item.getName()).append(" 已存在").append("<br/>");
                }
            } catch (Exception e) {
                log.error("error message: {}", e.getMessage());
                failureNum++;
                failureMsg.append(failureNum).append("、模板 ").append(item.getName()).append(" 导入失败").append("<br/>");
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：<br/>");
            throw new BizException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：<br/>");
        }
        return successMsg.toString();
    }

    @Override
    public List<TemplateConfig> listConfigByGroupId(Long groupId) {
        if (Objects.isNull(groupId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<TemplateConfig> lqw = TemplateConfig.lqw().eq(TemplateConfig::getGroupId, groupId);
        return this.templateConfigMapper.selectList(lqw);
    }
}
